// Copyright (C) Recursion Company. All rights reserved.

package vol // 本文件中所有名称均被编译器所约定

import (
	"errors"
)

//-------------------------------------------------------------  基本对象相关操作函数

// 返回pTestObject的火山对象访问接口,失败返回nil.
//
//	pTestObject: 所欲测试的对象指针
func GetObjectInterface(pTestObject any) IObject {
	if pTestObject == nil {
		return nil
	}

	var (
		vobi IObject
		ok   bool
	)
	if vobi, ok = pTestObject.(IObject); !ok {
		return nil
	}

	return vobi
}

// 返回pTestObject是否不为nil且为火山对象
//
//	pTestObject: 所欲测试的对象指针
func IsObject(pTestObject any) bool {
	if pTestObject == nil {
		return false
	}

	_, ok := pTestObject.(IObject)
	return ok
}

// 比较两个火山对象是否相等
func IsObjectEqual(pObjCompare1 IObject, pObjCompare2 IObject) bool {
	if pObjCompare1 == nil {
		return pObjCompare2 == nil
	}
	if pObjCompare2 == nil {
		return false
	}

	return pObjCompare1.VolGetThis() == pObjCompare2.VolGetThis()
}

// 检查所指定类型是否为火山对象类,如果不是则抛出异常.
func CheckClass[T any]() IObject {
	var obj any = new(T)
	return obj.(IObject)
}

// 返回pTestObject是否不为nil且为T类型
//
//	pTestObject: 所欲测试对象的指针,支持自动处理火山对象.
//	T: 所欲测试的对象类型
func IsInstanceOf[T any](pTestObject any) bool {
	var ok, blNotFirstCheck bool

	for pTestObject != nil {
		if _, ok = pTestObject.(*T); ok {
			return true
		}

		var vobi IObject
		if vobi, ok = pTestObject.(IObject); !ok {
			return false
		}

		if !blNotFirstCheck { // 首次检查?
			blNotFirstCheck = true
			pThisObject := vobi.VolGetThis()
			if pThisObject != pTestObject {
				pTestObject = pThisObject
				continue
			}
		}

		pTestObject = vobi.VolGetSuper()
	}

	return false
}

// 将pTestObject转换为T对象类型后返回,失败返回空对象.
//
//	pTestObject: 所欲测试对象的指针,支持自动处理火山对象.
//	T: 所欲转换到的对象类型
func CnvObj[T any](pTestObject any) *T {
	var ok, blNotFirstCheck bool

	for pTestObject != nil {
		var pobjResult *T
		if pobjResult, ok = pTestObject.(*T); ok {
			return pobjResult
		}

		var vobi IObject
		if vobi, ok = pTestObject.(IObject); !ok {
			return nil
		}

		if !blNotFirstCheck { // 首次检查?
			blNotFirstCheck = true
			pThisObject := vobi.VolGetThis()
			if pThisObject != pTestObject {
				pTestObject = pThisObject
				continue
			}
		}

		pTestObject = vobi.VolGetSuper()
	}

	// FatalError("Object convert failed")
	return nil
}

// 将data数据转换到T类型后返回
func CnvBase[T any](data any) T {
	var val T
	if data != nil {
		val, _ = data.(T)
	}
	return val
}

// 将data数据转换到T类型后返回. pblConvertSucceeded如果不为nil,则在其中返回是否转换成功.
func CnvBase2[T any](data any, pblConvertSucceeded *bool) T {
	var val T
	if data != nil {
		if pblConvertSucceeded != nil {
			val, *pblConvertSucceeded = data.(T)
		} else {
			val, _ = data.(T)
		}
	}
	return val
}

// 将 []T 数组转换为 []*T 数组后返回
func ObjAry2RefAry[T any](aryValue []T) []*T {
	var nLen = len(aryValue)
	var aryRef = make([]*T, nLen)

	for i := 0; i < nLen; i++ {
		aryRef[i] = &aryValue[i]
	}

	return aryRef
}

//-------------------------------------------------------------  对象类型数组新建操作

// 火山程序所允许的最大数组维数为6维
func MakeObjSlice6[E any](nDim1, nDim2, nDim3, nDim4, nDim5, nDim6 int) [][][][][][]*E {
	var ary = make([][][][][][]*E, nDim1)
	for nIndex := 0; nIndex < nDim1; nIndex++ {
		ary[nIndex] = MakeObjSlice5[E](nDim2, nDim3, nDim4, nDim5, nDim6)
	}
	return ary
}

func MakeObjSlice5[E any](nDim1, nDim2, nDim3, nDim4, nDim5 int) [][][][][]*E {
	var ary = make([][][][][]*E, nDim1)
	for nIndex := 0; nIndex < nDim1; nIndex++ {
		ary[nIndex] = MakeObjSlice4[E](nDim2, nDim3, nDim4, nDim5)
	}
	return ary
}

func MakeObjSlice4[E any](nDim1, nDim2, nDim3, nDim4 int) [][][][]*E {
	var ary = make([][][][]*E, nDim1)
	for nIndex := 0; nIndex < nDim1; nIndex++ {
		ary[nIndex] = MakeObjSlice3[E](nDim2, nDim3, nDim4)
	}
	return ary
}

func MakeObjSlice3[E any](nDim1, nDim2, nDim3 int) [][][]*E {
	var ary = make([][][]*E, nDim1)
	for nIndex := 0; nIndex < nDim1; nIndex++ {
		ary[nIndex] = MakeObjSlice2[E](nDim2, nDim3)
	}
	return ary
}

func MakeObjSlice2[E any](nDim1, nDim2 int) [][]*E {
	var ary = make([][]*E, nDim1)
	for nIndex := 0; nIndex < nDim1; nIndex++ {
		ary[nIndex] = MakeObjSlice1[E](nDim2)
	}
	return ary
}

func MakeObjSlice1[E any](nDim1 int) []*E {
	var ary = make([]*E, nDim1)

	for nIndex := 0; nIndex < nDim1; nIndex++ {
		ary[nIndex] = new(E)
		var obj any = ary[nIndex]
		if vobi, ok := obj.(IObject); ok { // 为火山对象?
			vobi.VolInit() // 将其初始化
		}
	}
	return ary
}

//-------------------------------------------------------------  基本数据类型数组新建操作

// 火山程序所允许的最大数组维数为6维
func MakeBaseSlice6[E any](nDim1, nDim2, nDim3, nDim4, nDim5, nDim6 int) [][][][][][]E {
	var ary = make([][][][][][]E, nDim1)
	for nIndex := 0; nIndex < nDim1; nIndex++ {
		ary[nIndex] = MakeBaseSlice5[E](nDim2, nDim3, nDim4, nDim5, nDim6)
	}
	return ary
}

func MakeBaseSlice5[E any](nDim1, nDim2, nDim3, nDim4, nDim5 int) [][][][][]E {
	var ary = make([][][][][]E, nDim1)
	for nIndex := 0; nIndex < nDim1; nIndex++ {
		ary[nIndex] = MakeBaseSlice4[E](nDim2, nDim3, nDim4, nDim5)
	}
	return ary
}

func MakeBaseSlice4[E any](nDim1, nDim2, nDim3, nDim4 int) [][][][]E {
	var ary = make([][][][]E, nDim1)
	for nIndex := 0; nIndex < nDim1; nIndex++ {
		ary[nIndex] = MakeBaseSlice3[E](nDim2, nDim3, nDim4)
	}
	return ary
}

func MakeBaseSlice3[E any](nDim1, nDim2, nDim3 int) [][][]E {
	var ary = make([][][]E, nDim1)
	for nIndex := 0; nIndex < nDim1; nIndex++ {
		ary[nIndex] = MakeBaseSlice2[E](nDim2, nDim3)
	}
	return ary
}

func MakeBaseSlice2[E any](nDim1, nDim2 int) [][]E {
	var ary = make([][]E, nDim1)
	for nIndex := 0; nIndex < nDim1; nIndex++ {
		ary[nIndex] = MakeBaseSlice1[E](nDim2)
	}
	return ary
}

func MakeBaseSlice1[E any](nDim1 int) []E {
	return make([]E, nDim1)
}

//-------------------------------------------------------------  其它

func Assert(blTestPass bool, strFailPrompt string) {
	if !blTestPass {
		if strFailPrompt == "" {
			panic(errors.New("Assert Failed"))
		} else {
			panic(errors.New("Assert Failed: " + strFailPrompt))
		}
	}
}

func FailAssert(blFail bool, strFailPrompt string) {
	Assert(!blFail, strFailPrompt)
}

func FatalError(strFailPrompt string) {
	panic(errors.New("Fatal Error: " + strFailPrompt))
}
